using System;
using AnimatingHair.Auxiliary;
using AnimatingHair.Entity.PhysicalEntity;
using OpenTK;

namespace AnimatingHair.Entity
{
    class Scene
    {
        public bool Up { get; set; }
        public bool Down { get; set; }
        public bool Left { get; set; }
        public bool Right { get; set; }

        public Hair Hair { get; set; }
        public Bust Bust { get; set; }

        public VoxelGrid VoxelGrid { get; set; }

        internal void StepEuler( double timeStep )
        {
            Hair.CalculateForces();
            Bust.CalculateForcesOnParticles( Hair.Particles );

            // 4. integrate forces (update positions and velocities)
            Hair.IntegrateForces( timeStep );

            // 5. update direction
            Hair.UpdateDirections();
        }

        internal void Step()
        {
            // 4. integrate forces (update positions and velocities)

            Vector3d forceOnBust = getMovementForce();

            RKStep( 0 );

            for ( int i = 1; i < 5; i++ )
            {
                Hair.CalculateForces();
                Bust.CalculateForcesOnParticles( Hair.Particles );

                Hair.ApplyForceOnRootParticles( forceOnBust );
                Bust.Force = forceOnBust;

                Hair.UpdateDirections();

                RKStep( i );
            }

            RKStep( 5 );

            // 5. update direction
            Hair.UpdateDirections();

            Bust.UpdateComponents();
        }

        private Vector3d getMovementForce()
        {
            Vector3d result = new Vector3d();
            if ( Up )
                result.Z -= 0.02;
            if ( Down )
                result.Z += 0.02;
            if ( Left )
                result.X -= 0.02;
            if ( Right )
                result.X += 0.02;

            if ( (result.X == 0 && result.Z == 0) || Bust.Velocity.Length > 0.2 )
            {
                result -= Bust.Velocity;
            }

            return result;
        }

        private void RKStep( int stepNumber )
        {
            Hair.RKStep( stepNumber );
            Bust.RKStep( stepNumber );
        }
    }
}
